<?php
/**
 * Created by PhpStorm.
 * User: whwyy
 * Date: 2018/4/4 0004
 * Time: 13:38
 */

namespace BeReborn\Database;

use BeReborn\Database\Filters;
use BeReborn\Database\Base\AbstractCollection;
use Exception;

/**
 * Class Collection
 * @package BeReborn\Database
 * @property-read $length
 */
class Collection extends AbstractCollection
{
	/**
	 * @return int
	 */
	public function getLength()
	{
		return count($this->_item);
	}

	/**
	 * @return array
	 */
	public function getItems()
	{
		return $this->_item; // TODO: Change the autogenerated stub
	}

	/**
	 * @param $field
	 *
	 * @return array|null
	 * @throws Exception
	 */
	public function values($field)
	{
		if (empty($field) || !is_string($field)) {
			return NULL;
		}
		$_tmp = [];
		$data = $this->toArray();
		foreach ($data as $val) {
			/** @var ActiveRecord $val */
			$_tmp[] = $val[$field];
		}
		return $_tmp;
	}

	/**
	 * @param string $field
	 * @return array|null
	 */
	public function keyBy(string $field)
	{
		$array = $this->toArray();
		$column = array_flip(array_column($array, $field));
		foreach ($column as $key => $value) {
			$column[$key] = $array[$value];
		}

		return $column;
	}

	/**
	 * @return $this
	 */
	public function orderRand()
	{
		shuffle($this->_item);
		return $this;
	}

	/**
	 * @param int $start
	 * @param int $length
	 *
	 * @return array
	 */
	public function slice($start = 0, $length = 20)
	{
		if (empty($this->_item) || !is_array($this->_item)) {
			return [];
		}
		if (count($this->_item) < $length) {
			return $this->_item;
		} else {
			return array_slice($this->_item, $start, $length);
		}
	}

	/**
	 * @param        $field
	 * @param string $setKey
	 *
	 * @return array|null
	 */
	public function column($field, $setKey = '')
	{
		$data = $this->toArray();
		if (empty($data)) {
			return [];
		}
		if (!empty($setKey) && is_string($setKey)) {
			return array_column($data, $field, $setKey);
		} else {
			return array_column($data, $field);
		}
	}

	/**
	 * @param $field
	 *
	 * @return float|int|null
	 */
	public function sum($field)
	{
		$array = $this->column($field);
		if (empty($array)) {
			return NULL;
		}
		return array_sum($array);
	}

	/**
	 * @return ActiveRecord|mixed
	 */
	public function current()
	{
		return current($this->_item);
	}

	/**
	 * @return int
	 */
	public function size()
	{
		return (int)count($this->_item);
	}

	/**
	 * @return array
	 * @throws
	 */
	public function toArray()
	{
		$array = [];
		foreach ($this->_item as $value) {
			if (!is_object($value)) {
				continue;
			}
			$array[] = $value->toArray();
		}
		$this->_item = [];
		return $array;
	}

	/**
	 * @throws Exception
	 * 批量删除
	 */
	public function delete()
	{
		$model = $this->model;
		if (!$model::hasPrimary()) {
			return false;
		}
		$ids = [];
		foreach ($this->_item as $item) {
			$ids[] = $item->{$model::getPrimary()};
		}
		$ids = array_filter($ids);
		if (empty($ids)) {
			return false;
		}
		return $this->model::find()
			->in($model::getPrimary(), $ids)
			->deleteAll();
	}

	/**
	 * @param array $condition
	 * @return Filters
	 * @throws
	 */
	public function filter(array $condition)
	{
		if (empty($condition)) {
			return new Filters($this->_item);
		}
		$_filters = [];
		foreach ($this->_item as $value) {
			$_value = $value;
			if ($_value instanceof ActiveRecord) {
				$_value = $_value->toArray();
			}
			$_tmp = array_intersect_key($_value, $condition);
			if (count(array_diff_assoc($_tmp, $condition)) > 0) {
				continue;
			}
			$_filters[] = $value;
		}
		return new Filters($_filters);
	}

	/**
	 * @param $key
	 * @param $value
	 * @return ActiveRecord|mixed|null
	 */
	public function exists($key, $value)
	{
		foreach ($this->_item as $item) {
			if ($item->$key === $value) {
				return $item;
			}
		}
		return null;
	}

	/**
	 * @return bool
	 */
	public function isEmpty()
	{
		return $this->size() < 1;
	}
}
